package org.example.Lock;


import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author : zhangbo
 * @data : 2024/7/17
 * @description :synchronized关键字可以使用任何对象作为锁对象，因为monitor对象存在于每个Java对象的对象头中。
 */
public class MySynchronized {
    public static void main(String[] args) {
        SharedObject obj = new SharedObject();
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                obj.increment();
            }
        });

        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                obj.increment();
            }
        });

        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Final count is: " + obj.getCount());
    }

    private static final Map<String, Map<String, Object>> cacheMap = new ConcurrentHashMap<>();

    static class SharedObject {
        private int count = 0;

        /**
         * increment方法使用了synchronized关键字，确保每次只有一个线程可以执行这个方法，从而避免了多线程同时修改count变量的问题。
         */
        public synchronized void increment() {
            count++;
        }

        public int getCount() {
            return count;
        }
    }


    public class test {
        public void mySet() {
            Stu stu = new Stu();
            synchronized (this) {
                if (stu.getAge().equals("18")) {
                    System.out.println("高中生");
                }
            }
            //与this一样
            synchronized (Test.class) {
                if (stu.getAge().equals("18")) {
                    System.out.println("高中生");
                }
            }
        }
    }


    /**
     * 线程安全：通过将stu对象作为锁，您确保了在执行同步代码块期间，只有一个线程可以访问这段代码。这有助于防止多个线程同时修改或访问stu对象的状态，从而避免数据竞争和不一致的问题。
     * <p>
     * 锁的范围限制：锁的作用域仅限于同步代码块内部。这意味着，一旦代码块执行完毕，锁将被释放，其他线程可以获取同一个stu对象的锁并执行自己的同步代码块。
     * <p>
     * 性能考虑：使用同步可能会影响程序的性能，因为它限制了并发性。如果多个线程需要频繁地访问和修改stu对象，这可能会导致线程争用锁，从而增加等待时间和降低性能。
     * <p>
     * 死锁风险：如果不正确地使用锁，尤其是在复杂的多线程程序中，可能会增加死锁的风险。死锁发生在两个或多个线程相互等待对方释放锁，但没有一个线程能够继续执行。
     * <p>
     * 重入性：Java的synchronized关键字是可重入的，这意味着如果一个线程已经拥有某个对象的锁，它可以再次进入该对象的同步代码块而不会阻塞。
     * <p>
     * 锁的公平性：默认情况下，synchronized锁是非公平的，这意味着锁的获取顺序不一定遵循请求顺序。如果需要，可以通过使用java.util.concurrent.locks.ReentrantLock并设置其公平性来实现公平锁。
     * <p>
     * 不可中断性：使用synchronized时，等待锁的线程不能响应中断。也就是说，如果一个线程正在等待锁，它不能被中断来响应中断请求。
     * <p>
     * 锁的可见性：synchronized确保了锁的可见性，即一个线程对共享变量的修改对其他线程是可见的。
     * <p>
     * 请注意，使用synchronized时，应该谨慎选择锁对象，并确保锁的使用不会引入不必要的性能问题或死锁风险
     */
    public class Test {
        public void mySet(Stu stu) {
            synchronized (stu) {
                if (stu.getAge().equals("18")) {
                    System.out.println("高中生");
                }
            }
        }
    }

    public class Test2 {
        private final Object lock = new Object();

        public void mySet() {
            Stu stu = new Stu();
            synchronized (lock) {
                if (stu.getAge().equals("18")) {
                    System.out.println("高中生");
                }
            }
        }
    }
}
